﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;

namespace Golden.Gegerla.Service.Upload.DataContract
{
    /// <summary>
    /// Session Cache
    /// </summary>
    /// <typeparam name="TUploadSession">Type of the Session to Cache</typeparam>
    internal class SessionCache<TUploadSession> where TUploadSession : UploadSession, new()
    {
        /// <summary>
        /// Get Item by Key
        /// </summary>
        /// <param name="key">Key</param>
        /// <returns>Upload Session Object</returns>
        internal TUploadSession this[Guid key]
        {
            get
            {
                if (HttpRuntime.Cache == null)
                    return default(TUploadSession);

                return HttpRuntime.Cache.Get(key.ToString()) as TUploadSession;
            }
        }

        /// <summary>
        /// Add a new Item to Cache
        /// </summary>
        /// <param name="uploadSession">Upload Session Object</param>
        internal void Add(TUploadSession uploadSession)
        {
            if (uploadSession == null)
                throw new ArgumentNullException("uploadSession");
            if (HttpRuntime.Cache == null)
                throw new Exception("Can't add Upload Session to Cache. Cache is null.");

            if (!this.Contains(uploadSession))
            {
                HttpRuntime.Cache.Add(uploadSession.Token.ToString(), uploadSession, null,
                                      Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5),
                                      CacheItemPriority.NotRemovable,
                                      new CacheItemRemovedCallback(this.SessionRemoved));
            }
            else
            {
                HttpRuntime.Cache.Insert(uploadSession.Token.ToString(), uploadSession);
            }
        }

        /// <summary>
        /// Check if the Cache contains the given Element
        /// </summary>
        /// <param name="uploadSession">Object to check</param>
        /// <returns>Boolean Value</returns>
        internal bool Contains(TUploadSession uploadSession)
        {
            if (HttpRuntime.Cache == null)
                throw new Exception("Can't access Upload Session Cache. Cache is null.");

            return this.Contains(uploadSession.Token);
        }

        /// <summary>
        /// Check if the Cache contains the Element with the given Key
        /// </summary>
        /// <param name="key">Key of the Element</param>
        /// <returns>Boolean Value</returns>
        private bool Contains(Guid key)
        {
            TUploadSession uploadSessionFromCache = HttpRuntime.Cache.Get(key.ToString()) as TUploadSession;

            return uploadSessionFromCache == default(TUploadSession) ? false : true;
        }

        /// <summary>
        /// Remove a Session from Cache
        /// </summary>
        /// <param name="uploadSession">Session to Remove</param>
        internal void Remove(TUploadSession uploadSession)
        {
            if(HttpRuntime.Cache == null)
                throw new Exception("Can't access Upload Session to Cache. Cache is null.");
            if (uploadSession.State != UploadState.Completed || uploadSession.State == UploadState.Failed)
                throw new Exception("Session is not Completed and will not be removed from cache.");

            if (!this.Contains(uploadSession))
            {
                HttpRuntime.Cache.Remove(uploadSession.Token.ToString());
            }
        }

        /// <summary>
        /// Occurs if a Session is Removed from the Cache
        /// </summary>
        /// <param name="key">Key of the Removed Session</param>
        /// <param name="itemtoremove">Item to Remove</param>
        /// <param name="reason">Reason why the Session is removed.</param>
        private void SessionRemoved(string key, object itemtoremove, CacheItemRemovedReason reason)
        {
        }
    }
}